package com.live.stamp.base.validation;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.container.core.common.BusinessException;

import java.io.File;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * 生成参数验证对象
 */
public class ParamHandlerManager {
    private static final Logger logger = LoggerFactory.getLogger(ParamHandlerManager.class);

    private static ParamHandler paramHeadHandler = null;

    private ParamHandlerManager() {
    }
    //初始化参数验证责任链
    static {
        try {
            initParamHandle();
        } catch (Exception e) {
            logger.error("init paramHandle error！", e);
        }
    }

    public static ParamHandler getHeadHandle(){
        return paramHeadHandler;
    }

    /**
     * 初始化 参数验证组件
     * @throws Exception
     */
    private static void initParamHandle() throws Exception {
        logger.info("initParamHandle start......");
        Class clazz = ParamHandler.class;
        //获取clazz所在的包名
        String pk = clazz.getPackage().getName();
        //获取包下的所有class
        List<Class> children = getPackageClasses(pk);
        ParamHandler tempHandle = null;
        for (Class child : children) {
            if (clazz == child) {
                continue;
            }
            if(!clazz.isAssignableFrom(child)){
                continue;
            }

            if (tempHandle == null) {
                tempHandle = (ParamHandler) child.newInstance();
                paramHeadHandler = tempHandle;
            } else {
                ParamHandler p = (ParamHandler) child.newInstance();
                tempHandle.setNext(p);
                tempHandle = p;
            }
        }
    }

    /**
     * 获取包下的所有class类集合
     * @param pk 包名
     * @return 包名下 class类的集合
     * @throws Exception
     */
    private static List<Class> getPackageClasses(String pk) throws Exception {
        /*
            1.获取validation包对应url
            2.判断url是file，还是jar文件里面的file
         */
        String path = pk.replace(".", "/");
        URL url = Thread.currentThread().getContextClassLoader().getResource(path);

        if("file".equals(url.getProtocol())){
            return getClasses(new File(url.getFile()), pk);
        }else if("jar".equals(url.getProtocol())){
            JarFile jarFile = ((JarURLConnection)url.openConnection()).getJarFile();
            return getJarClasses(jarFile, path);
        }
        return null;
    }

    /**
     * 解析JarFile文件
     * @param jar jarFile
     * @param pkPath 包路径
     * @return class集合
     * @throws Exception
     */
    private static List<Class> getJarClasses(JarFile jar, String pkPath) throws Exception{
        List<Class> classes = new ArrayList<>();
        Enumeration<JarEntry> entries = jar.entries();
        while (entries.hasMoreElements()) {
            JarEntry entry = entries.nextElement();
            String name = entry.getName();
            if (name.charAt(0) == '/') {
                name = name.substring(1);
            }
            if (name.contains(pkPath) && name.endsWith(".class")) {
                String className = name.substring(0, name.length() - 6);
                classes.add(Class.forName(className.replace("/", ".")));
            }
        }
        return classes;
    }

    /**
     * 解析File文件
     * @param dir file文件
     * @param pk 路径
     * @return class集合
     * @throws Exception
     */
    private static List<Class> getClasses(File dir, String pk) throws Exception{
        List<Class> classes = new ArrayList<>();
        if (!dir.exists()) {
            throw new BusinessException(pk + " is not exist!");
        }
        for (File f : dir.listFiles()) {
            String name = f.getName();
            if (name.endsWith(".class")) {
                classes.add(Class.forName(pk + "." + name.substring(0, name.length() - 6)));
            }
        }
        return classes;
    }
}
